/**
 * @author Austin Andrews (Templarian)
 * @authorurl http://templarian.com
 * @framework DD Framework
 * @licence MIT License
 * @licenceurl http://ddframework.googlecode.com/svn/trunk/license.txt
 * @overview Convert Savvy content to DOM.
 */
dd.savvy({
    /**
     * Comment Here
     */
    func:function(o, s)
    {
        o.text = o.text || "";
        o.parent = o.parent || dd.body;
        o.override = o.override || function(){};
        o.success = o.success || function(){};
        o.failure = o.failure || function(){};
        var e = "element" in o,
            a = dd.savvy.prepare(o.text),
            tN = "", // Tag Name
            t = "", // Temp Text
            nL = true, // New Line
            cB = false, // Code Block
            cBM = false, // Code Block ``` ```
            cBB = false, // Code Block {{{ }}}
            cBL = "text", // Code Block Language
            cBT = "", // Code Block Text
            isVar = false,
            lC = 0, // Line Count
            cC = 1, // Column Count
            iN = false, // Ignore Next
            isComment = false,
            property = {}; // Properties
        for(var i = 0; i < a.length; i++)
        {
            // Current, Before, Next
            var c  = a[i];
            var b = i == 0
                ? null
                : a[i - 1];
            var n = i == a.length - 1
                ? null
                : a[i + 1];
            // Handle New Line
            if(c == "\n")
            {
                lC++;
                cC = 1;
            }
            // Handle the Storage of Varaibles
            if(b == "\n" && c == "@" && n != "*" && !cBM && !cBB)
            {
                i++;
                t = ""; // Get rid of that
                var vN = ""; // Variable Name
                var vT = ""; // Variable Text
                var vB = false; // Variable Block
                var vI = false;
                while((a[i] != "\n" || vB) && i < a.length)
                {
                    if(vI)
                    {
                        if((a[i] == "}" && a[i + 1] == "\n") && vB)
                        {
                            vB = false;
                        }
                        else
                        {
                            vT += a[i];
                        }
                    }
                    else if((a[i] == " " || a[i] == "{") && !vI)
                    {
                        if(a[i] == "{") // Block
                        {
                            vB = true;
                        }
                        vI = true;
                    }
                    else if(!vI)
                    {
                        vN += a[i];
                    }
                    i++;
                }
                property[vN] = vT;
            }
            else if(c == "@" && n == "*" && !cB)
            {
                isComment = true;
                continue;
            }
            else if(c == "@" && b == "*" && !cB)
            {
                isComment = false;
                continue;
            }
            else if(isComment)
            {
                continue;
            }
            if(((a[i] == "#" || a[i] == "=") && a[i + 1] == " ")
                && nL && !cB)
            {
                tN = a[i] == "#" || a[i] == "=" ? t + a[i] : t;
                t = "";
                nL = false;
                i++;
            }
            else if((a[i] == "`" && a[i + 1] == "`" && a[i + 2] == "`" && !cBM && !cBB) ||
                    ((a[i] == "{" && a[i + 1] == "{" && a[i + 2] == "{") &&
                     (a[i + 3] == "{" || a[i + 3] == "\n" && !cBB && !cBM)
                    ) && !cB)
            {
                if(a[i] == "`")
                {
                    cBM = true;
                }
                if(a[i] == "{")
                {
                    cBB = true;
                }
                i += a[i + 3] != "\n" && a[i] == "`" ? 2 : 3;
                t = "";
                cBL = "";
                var title = "";
                if(a[i] == "{" && cBB)
                {
                    i++;
                    while (a[i] != "}")
                    {
                        cBL += a[i];
                        i++;
                    }
                    i++;
                    while (a[i] != "\n")
                    {
                        title += a[i];
                        i++;
                    }
                    cBT = "";
                }
                else if(a[i] != "\n" && cBM)
                {
                    i++;
                    var f = false;
                    while (a[i] != "\n")
                    {
                        if(a[i] == " " && !f)
                        {
                            f = true;
                            i++;
                            continue;
                        }
                        if(f)
                        {
                            title += a[i];
                        }
                        else
                        {
                            cBL += a[i];
                        }
                        i++;
                    }
                }
                else
                {
                    cBL = "text";
                }
                if(title != "")
                {
                    dd(o.parent).addElement("div", title, {"class":"code-title"});
                    cBT = title;
                }
                cB = true;
            }
            else if(a[i] == "\n" &&
                    ((a[i + 1] == "`" && a[i + 2] == "`" && a[i + 3] == "`" && cBM) ||
                     (a[i + 1] == "}" && a[i + 2] == "}" && a[i + 3] == "}" && cBB)
                    ) && cB)
            {
                // Quick Check for IE9 bug
                if(/^\n/.test(t))
                {
                    t = t.substr(1).replace(/\n\n/g, "\n");
                }
                var pre = dd(o.parent).addElement("pre", t, {"class":cBT == "" ? "" : "code-has-title"});
                if(cBL != "")
                {
                    // C# = c-sharp, C++ = plus
                    dd(pre).addClass("code-" + dd.toL(cBL).replace("#", "-sharp")
                                                          .replace("+", "-plus")
                                                          .replace(".", "-dot"));
                }
                cBM = false;
                cbL = false;
                cB = false;
                t = "";
                i += 4;
            }
            else if(a[i] == "\n" && (a[i + 1] == "=" || a[i + 1] == "-" || a[i + 1] == "~" || a[i + 1] == "\n") && !cB)
            {
                var v = dd.savvy.block(tN, t);
                if(a[i + 1] == "=" || a[i + 1] == "-" || a[i + 1] == "~")
                {
                    v.tag = a[i + 1] == "=" ? "h1" : a[i + 1] == "-" ? "h2" : "h3";
                }
                if(!iN && v.text != "" )
                {
                    if(v.isImage)
                    {
                        v.tag = "figure";
                    }
                    var p = dd(o.parent).addElement(v.tag);
                    if(v.classes != "")
                    {
                        dd(p).addClass(v.classes);
                    }
                    dd(p).css(v.styles);
                    dd.savvy.inline(p, v.text, property);
                }
                iN = a[i + 1] == "=" || a[i + 1] == "-";
                tN = "";
                t = "";
                i++;
                nL = true;
            }
            else if(a[i] == "\n" && a[i + 1] == "|" && !cB)
            {
                // Table here
                var blah = dd(o.parent).addElement("span", "Table Support Here");
                dd(blah).css({"background":"red"});
            }
            else
            {
                if(!(t == "" && c == "\n"))
                {
                    t += c;
                }
            }
            cC++;
        }
        var sc = {self:o.parent.self, property:property};
        dd.combine(sc, s);
        o.success.call(sc);
    },
    prepare:function(t)
    {
        var a = t.split("");
        a.unshift("\n");
        for (var i = 0; i < a.length; i++)
        {
            if (a[i] == "\r")
            {
                a.splice(i, 1);
                i--;
            }
        }
        a.push("\n", "\n");
        return a;
    },
    element:{
        paragraph:function()
        {
            
        },
        header:function()
        {
            
        },
        image:function()
        {
            
        }
    },
    properties:{},
    applyStyle:function(p, s, t)
    {
        var tag = {
            code:"code",
            strong:"strong",
            emphasis:"em",
            inserted:"ins",
            deleted:"del",
            subscript:"sub",
            superscript:"sup",
            span:"span"
        };
        for(i in s)
        {
            if(s[i] != -1)
            {
                p = dd(p).addElement(tag[i]);
            }
        }
        dd(p).addText(t);
    },
    inline:function(p, t, property)
    {
        var v = t.split("");
        t = "";
        var lT = ""; // Link Text
        var sL = -1; // Start Link
        var sI = -1; // Start Image
        var sPL = -1; // Start ( Link
        var sPI = -1; // Start ( Image
        var pC = 0; // Count ( = +1 and ) = -1
        var sV = -1; // Start Variable
        var prev = -1; // Previous
        var s = { // Move ^ below
            code:-1,
            strong:-1,
            emphasis:-1,
            inserted:-1,
            deleted:-1,
            subscript:-1,
            superscript:-1,
            span:-1
        };
        var charToName = {
            "`":"code",
            "*":"strong",
            "_":"emphasis",
            "+":"inserted",
            "-":"deleted",
            "~":"subscript",
            "^":"superscript",
            "%":"span"
        };
        var is = {
            variable:false,
            image:false,
            imageB:false,
            link:false,
            linkB:false
        };
        for(var i = 0; i < v.length; i++)
        {
            var c = v[i];
            var b = i == 0 || (c == "\n" && i == 1)
                ? null
                : v[i - 1];
            var n = i == v.length - 1
                ? null
                : v[i + 1];
            if((n == " " ||
                n == ")" ||
                i == v.length - 1) &&
               is.variable)
            {
                var vn = (t + v[i]).substr(sV);
                if(vn in property)
                {
                    t = t.substr(0, t.length - vn.length + 1) + property[vn];
                }
                else
                {
                    dd.savvy.error(p, "Variable Undefined");
                }
                is.variable = false;
                continue;
            }
            else if(v[i] == ")" && (is.image || is.link) && is.variable)
            {
                t = property[t];
            }
            switch(v[i])
            {
                case "\n":
                    if(b != null) // First Link Blank
                    {
                        dd(p).addText(t);
                        dd(p).addElement("br");
                        t = "";
                    }
                    break;
                case "\\": // Esacape
                    if(n == "`" ||
                       n == "*" ||
                       n == "_" ||
                       n == "+" ||
                       n == "-" ||
                       n == "~" ||
                       n == "^" ||
                       n == "%" ||
                       n == "[")
                    {
                        t += n;
                        i++;
                    }
                    break;
                case "[":
                    if(b == "!")
                    {
                        sI = t.length + 1;
                        is.image = true;
                        is.imageB = true;
                    }
                    else
                    {
                        sL = t.length + 1;
                        is.link = true;
                        is.linkB = true;
                    }
                    t += v[i];
                    break;
                case "]":
                    if(n == "(" && is.image && is.imageB)
                    {
                        lT = t.substr(sI);
                        is.imageB = false;
                        sPI = t.length;
                    }
                    else if(n == "(" && is.link && is.linkB)
                    {
                        lT = t.substr(sL);
                        is.linkB = false;
                        pC = 0;
                        sPL = t.length;
                    }
                    else
                    {
                        is.image = false;
                        is.link = false;
                    }
                    t += v[i];
                    break;
                case "(":
                    if(!is.linkB && is.link)
                    {
                        pC++;
                    }
                    t += v[i];
                    break;
                case ")":
                    if(is.image && !is.imageB && !is.link)
                    {
                        if(t.substring(0, sI - 2) !== "")
                        {
                            dd(p).addText(t.substring(0, sI - 2));
                        }
                        dd(p).addElement("img", {
                            "src":t.substr(sPI + 2),
                            "alt":lT
                        });
                        is.image = false;
                        t = "";
                    }
                    else if(is.link && !is.linkB)
                    {
                        if(pC == 1)
                        {
                            if(t.substring(0, sL - 1) !== "")
                            {
                                dd(p).addText(t.substring(0, sL - 1));
                            }
                            var aL = dd.savvy.link(t.substr(sPL + 2));
                            if(aL)
                            {
                                var a = dd(p).addElement("a", {"href":aL.href});
                                if(aL.title !== "")
                                {
                                    dd(a).setAttribute("title", aL.title);
                                }
                                // Throw it back through the parser.
                                dd.savvy.inline(a, lT, property);
                            }
                            else
                            {
                                dd.savvy.error(p, "Link Format Unsupported");
                            }
                            is.link = false;
                            t = "";
                        }
                        else
                        {
                            pC--;
                            t += v[i];
                        }
                    }
                    else
                    {
                        t += v[i];
                    }
                    break;
                case "@": // Variables
                    // Code Later
                    if(s.code == -1)
                    {
                        if(n != "@")
                        {
                            is.variable = true;
                            sV = t.length;
                        }
                        else
                        {
                            t += v[i];
                            i++;
                        }
                    }
                    else
                    {
                        t += v[i];
                    }
                    break;
                case "`":
                case "*": // Strong
                case "_": // Emphasis
                case "+": // Inserted
                case "-": // Deleted
                case "~": // Subscript
                case "^": // Superscript
                case "%": // Span
                    if(is.link || (c != "`" && !((b == " " || b === null) || (n == " " || n === null))))
                    {
                        t += v[i];
                        continue;
                    }
                    var c = charToName[v[i]];
                    if(s.code != -1)
                    {
                        if(v[i] != "`")
                        {
                            t += v[i];
                            continue;
                        }
                    }
                    if(prev != -1)
                    {
                        if(t.substr(0, prev - 1) != "")
                        {
                            dd(p).addText(t.substr(0, prev - 1));
                        }
                        dd.savvy.applyStyle(p, s, t.substr(prev));
                        t = "";
                    }
                    if(s[c] != -1)
                    {
                        s[c] = -1;
                    }
                    else
                    {
                        s[c] = t.length;
                        t += v[i];
                    }
                    prev = t.length;
                    break;
                default:
                    t += v[i];
            }
        }
        if(t != "")
        {
            dd(p).addText(t);
        }
    },
    link:function(text)
    {
        for(var i = 0; i < text.length; i++)
        {
            var fS = false; // First Space
            if(text[i] === " ")
            {
                return {
                    href:text.substr(0, i),
                    title:text.substr(i + 1)
                };
            }
            else if(i === text.length - 1)
            {
                return {
                    href:text,
                    title:""
                };
            }
        }
        return false;
    },
    block:function(n, text)
    {
        var r = {
            isImage:false,
            text:text,
            tag:"p",
            classes:"",
            styles:{}
        };
        // For speed reasons, minimal check for image '![ )' will match
        if(text.length > 2)
        {
            if(text[0] == "!" && text[1] == "[" && text[text.length - 1] == ")")
            {
                r.isImage = true;
            }
        }
        if(n.match(/={1,6}|#{1,6}/))
        {
            var c = n.length;
            var cc = c + 1;
            r.tag = "h" + c;
            if(r.text.length > c)
            {
                if(r.text.substring(r.text.length - c) == n)
                {
                    r.text = r.text.substring(0, r.text.length - c);
                }
                else if(r.text.substring(r.text.length - cc) == " " + n)
                {
                    r.text = r.text.substring(0, r.text.length - cc);
                }
            }
            return r;
        }
        var v = n.split("");
        var t = "";
        var isTag = true;
        for(var i = 0; i < v.length; i++)
        {
            switch(v[i])
            {
                case "(":
                    if(isTag)
                    {
                        r.tag = t;
                        isTag = false;
                    }
                    t = "";
                    break;
                case ")":
                    r.classes = t;
                    t = "";
                    break;
                case "{":
                    if(isTag)
                    {
                        r.tag = t;
                        isTag = false;
                    }
                    t = "";
                    break;
                case "}":
                    var ts = t.split(";");
                    for(var j = 0; j < ts.length; j++)
                    {
                        var p = ts[j].split(":");
                        r.styles[p[0]] = p[1];
                    }
                    t = "";
                    break;
                default:
                    t += v[i];
            }
            if(i == v.length - 1 && t != "")
            {
                r.tag = t;
            }
        }
        return r;
    },
    error:function(p, text)
    {
        dd(p).addElement("code", text, {"class":"savvy-error"});
    },
    paragraph:function()
    {
        
    },
    header:function()
    {
        
    },
    fn:{
        /**
         * Comment Here
         */
        savvy:function(o, s)
        {
            s = s || {};
            if(dd.is(o, "string"))
            {
                return dd.savvy({
                    text:o,
                    parent:this
                }, s);
            }
            else
            {
                return dd.savvy({
                    text:o.text,
                    parent:this,
                    override:o.override || false,
                    success:o.success || false,
                    failure:o.failure || false
                }, s);
            }
        }
    }
});